package com.sts.source.impl;

import cn.hutool.core.util.StrUtil;
import com.sts.source.StsSource;
import com.sts.source.model.ExcelSourceConfig;
import lombok.extern.slf4j.Slf4j;
import org.ttzero.excel.reader.ExcelReader;
import org.ttzero.excel.reader.Row;
import org.ttzero.excel.reader.Sheet;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

@Slf4j
public class ExcelSourceImpl implements StsSource {

    private ExcelReader excelReader;
    private final ExcelSourceConfig excelSourceConfig;

    public ExcelSourceImpl(ExcelSourceConfig excelSourceConfig) {
        this.excelSourceConfig = excelSourceConfig;
    }

    @Override
    public List<String> getHeader() {
        if (!excelSourceConfig.isHasHeader()) {
            // false: 文件没有头，用指定的头
            return excelSourceConfig.getHeaderList();
        }

        try (ExcelReader excelReader = buildExcelReader()) {
            Map<String, Object> headMap = getSheet(excelReader)
                    .getHeader()
                    .toMap();

            return headMap.values()
                    .stream()
                    .filter(Objects::nonNull)
                    .map(item -> (String) item)
                    .toList();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @Override
    public Stream<List<String>> getDataStream() {
        excelReader = buildExcelReader();
        Stream<Row> stream = getSheet(excelReader).rows();

        if (excelSourceConfig.isHasHeader()) {
            // true: 文件有头，需要跳过第一行头数据
            stream = stream.skip(1);
        }
        return stream.filter(item -> !item.isBlank())
                .map(item -> {
                    Map<String, Object> map = item.toMap();
                    return map.values()
                            .stream()
                            .map(this::getCellValue)
                            .toList();
                });
    }

    @Override
    public void close() throws Exception {
        if (excelReader != null) {
            excelReader.close();
            log.info("ExcelReader Closed");
        }
    }

    private String getCellValue(Object o) {
        return (Objects.nonNull(o) && StrUtil.isNotBlank(String.valueOf(o))) ? String.valueOf(o) : null;
    }

    private Sheet getSheet(ExcelReader excelReader) {
        Sheet sheet;
        if (StrUtil.isNotBlank(excelSourceConfig.getSheetName())) {
            sheet = excelReader.sheet(excelSourceConfig.getSheetName());
        } else {
            sheet = excelReader.sheet(0);
        }

        return sheet;
    }

    private ExcelReader buildExcelReader() {
        try {
            return ExcelReader.read(Paths.get(excelSourceConfig.getFilePath()));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}
